#include "../include/head.h"

int CalMD5(char* filepath, char* md5)
{
    printf("计算MD5中...\n");
    MD5_CTX ctx;
    MD5_Init(&ctx);
    int openfd = open(filepath,O_RDWR);

    if(openfd==-1)
    {
        // printf("file_path = %s\n", filepath);
        return -1;
    }
    char buf[4096];
    unsigned char md[16];
    while(1)
    {
        bzero(buf,4096);
        ssize_t sret = read(openfd,buf,sizeof(buf));
        if(sret == 0)
        {
            break;
        }
        MD5_Update(&ctx,buf,sret);
    }
    MD5_Final(md,&ctx);
    for(int i=0;i<16;++i)
    {
        char temp[3]={0};
        sprintf(temp,"%02x",md[i]);
        strcat(md5,temp);
    }
    close(openfd);
    return 0;
}

int salt_create(char* desc)
{
    char salt_array[64]={
        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
        'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
        'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '/'
        };

    srand(time(NULL));
    char arr[21]={0};
    for(int i=0;i<16;i++){
        int x=rand()%64;
        arr[i]=salt_array[x];
    }
    // printf("随机生成%s\n",arr);

    char pre[]="$6$";
    char suf[]="$";
    snprintf(desc,30,"%s%s%s",pre,arr,suf);
    int n=strlen(desc);
    // printf("%s的长度为%d\n",desc,n);

    return 0;
    //
}

// 带安全限制的版本 的字符串截取
int getstr(const char *src, int n, char *dest, size_t dest_size) {
    char *workbuf = strdup(src); // 创建可修改副本
    if(!workbuf) return -1;

    char *token = strtok(workbuf, " ");
    int count = 1;
    int result = -1;

    while(token) {
        if(count == n) {
            strncpy(dest, token, dest_size-1);
            dest[dest_size-1] = '\0';
            result = 0;
            break;
        }
        token = strtok(NULL, " ");
        count++;
    }

    free(workbuf);
    return result;
}

//判断用户输入的参数个数是否合规
int checkout_num(const char *buf){
    char tmp[4096]={0};
    memcpy(tmp,buf,strlen(buf));
    char *p=strtok(tmp," ");
    int real=1;
    while(p!=NULL){
        p=strtok(NULL," ");
        real++;
    }
    --real; //去掉加NULL多加的一次
    return  real;
}

//初步判断用户输入
int simplejudge(char* readbuf,int* target,char *now_path_buf)
{
    int ret=checkout_num(readbuf);
    if(ret>3){
        printf("用户输入的格式有错误，请重新输入!\n");
        return -1;
    }

    char buf[1024]={0};
    getstr(readbuf,1,buf,1024);
    // printf("用户命令：%s\n",buf);

    if(strcmp(buf,"cd")==0)
    {
        if (checkout_num(readbuf) != 2)
        {
            printf("用户输入的格式有错误，请重新输入!\n");
            return -1;
        }
        *target=C_OP_CD;
    }
    else if(strcmp(buf,"ls")==0)
    {
        if(checkout_num(readbuf)!=1){
            printf("用户输入的格式有错误，请重新输入!\n");
            return -1;
        }
        *target=C_OP_LS;
    }
    else if(strcmp(buf,"pwd")==0)
    {
        if(checkout_num(readbuf)!=1){
            printf("用户输入的格式有错误，请重新输入!\n");
            return -1;
        }
        printf("%s\n", now_path_buf);
        return -1;
    }
    else if (strcmp(buf, "rmdir") == 0)
    {
        if(checkout_num(readbuf)!=2){
            printf("用户输入的格式有错误，请重新输入!\n");
            return -1;
        }
        *target=C_OP_RMDIR;
    }
    else if (strcmp(buf, "mkdir") == 0)
    {

        if(checkout_num(readbuf)!=2){
            printf("用户输入的格式有错误，请重新输入!\n");
            return -1;
        }
        *target=C_OP_MKDIR;
    }
    else if (strcmp(buf, "remove") == 0)
    {
        if(checkout_num(readbuf)!=2){
            printf("用户输入的格式有错误，请重新输入!\n");
            return -1;
        }
        *target=C_OP_REMOVE;
    }
    else if(strcmp(buf,"gets")==0){
        // printf("read_buf = %s\n", readbuf);
        if (checkout_num(readbuf) != 3)
        {
            printf("用户输入的格式有错误，请重新输入!\n");
            return -1;
        }
        char p[64]={0}; 
        getstr(readbuf,3,p,64);
        if(opendir(p)==NULL){
            printf("此路径不存在!\n");
            return -1;
        }
        *target=C_OP_GETS_QUERY;
    }
    else if(strcmp(buf,"puts")==0){
        if(checkout_num(readbuf)!=3){
            printf("用户输入的格式有错误，请重新输入!\n");
            return -1;
        }
        char p[64]={0};
        getstr(readbuf,2,p,64);
        if(access(p,F_OK)==-1){
            printf("上传的文件不存在!\n");
            return -1;
        }
        *target=C_OP_PUTS_QUERY;
    }
    else
    {
        printf("用户输入的命令有错误，请重新输入!\n");
        return -1;
    }
    return 0;
}



int submit(int netfd,char* buf,int target)
{   //封装包，上传
    RequestPackage* train=(RequestPackage *)calloc(1,sizeof(RequestPackage));
    // char vir_path[1024]={0};
    char tmp[1024]={0};
    char tmpp[1024]={0};
    char tmpbuf[2049]={0};
    switch (target)
    {
    case C_OP_LS:
        train->type=C_OP_LS;
        send(netfd,&train->type,sizeof(int),MSG_NOSIGNAL);
        train->args_len=0;
        send(netfd,&train->args_len,sizeof(train->args_len),MSG_NOSIGNAL);
        break;
    case C_OP_CD:
        // 发T
        train->type=C_OP_CD;
        send(netfd,&train->type,sizeof(int),MSG_NOSIGNAL);

        // 发args
        bzero(tmp,sizeof(tmp));
        getstr(buf,2,tmp,1024);
        train->args_len=strlen(tmp);
        send(netfd,&train->args_len,sizeof(int),MSG_NOSIGNAL);
        memcpy(train->args_val,tmp,strlen(tmp));
        send(netfd,train->args_val,train->args_len,MSG_NOSIGNAL);
        break;
    case C_OP_RMDIR:
        train->type=C_OP_RMDIR;
        send(netfd,&train->type,sizeof(int),MSG_NOSIGNAL);

        // 发args
        bzero(tmp,sizeof(tmp));
        getstr(buf,2,tmp,1024);
        train->args_len=strlen(tmp);
        send(netfd,&train->args_len,sizeof(int),MSG_NOSIGNAL);
        memcpy(train->args_val,tmp,strlen(tmp));
        send(netfd,train->args_val,train->args_len,MSG_NOSIGNAL);

        break;
    case C_OP_MKDIR:
        train->type=C_OP_MKDIR;
        send(netfd,&train->type,sizeof(int),MSG_NOSIGNAL);

        // 发args
        bzero(tmp,sizeof(tmp));
        getstr(buf,2,tmp,1024);
        train->args_len=strlen(tmp);
        send(netfd,&train->args_len,sizeof(int),MSG_NOSIGNAL);
        memcpy(train->args_val,tmp,strlen(tmp));
        send(netfd,train->args_val,train->args_len,MSG_NOSIGNAL);
        break;

    case C_OP_REMOVE:
        train->type=C_OP_REMOVE;
        send(netfd,&train->type,sizeof(int),MSG_NOSIGNAL);
        
        // 发args
        bzero(tmp,sizeof(tmp));
        getstr(buf,2,tmp,1024);
        train->args_len=strlen(tmp);
        send(netfd,&train->args_len,sizeof(int),MSG_NOSIGNAL);
        memcpy(train->args_val,tmp,strlen(tmp));
        send(netfd,train->args_val,train->args_len,MSG_NOSIGNAL);
        break;
        break;
    case C_OP_GETS_QUERY:

        train->type=C_OP_GETS_QUERY;
        send(netfd,&train->type,sizeof(int),MSG_NOSIGNAL);

        // 发args
        bzero(tmp,sizeof(tmp));
        getstr(buf,2,tmp,1024); 
        bzero(tmpp,sizeof(tmpp));
        getstr(buf,3,tmpp,1024);

        bzero(tmpbuf,sizeof(tmpbuf));
        snprintf(tmpbuf, sizeof(tmpbuf), "%s %s", tmp,tmpp);
         
        train->args_len=strlen(tmpbuf);
        memcpy(train->args_val,tmpbuf,train->args_len);
        send(netfd,&train->args_len,sizeof(int),MSG_NOSIGNAL);
        send(netfd,train->args_val,train->args_len,MSG_NOSIGNAL);

        break;
    case C_OP_PUTS_QUERY:

            train->type=C_OP_PUTS_QUERY;
            // printf("bufff = %s\n", buf);

            // 发args
            bzero(tmp,sizeof(tmp));
            getstr(buf,2,tmp,1024); 
            bzero(tmpp,sizeof(tmpp));
            getstr(buf,3,tmpp,1024);
            char md5[33]={0};
            if(CalMD5(tmp,md5)==-1)
            {
                printf("计算md5失败！\n");
                return -1;
            };

            bzero(tmpbuf,sizeof(tmpbuf));
            snprintf(tmpbuf, sizeof(tmpbuf), "%s %s %s", tmp,tmpp,md5);
            // printf("puts args:%s\n",tmpbuf); 
            train->args_len=strlen(tmpbuf);
            memcpy(train->args_val,tmpbuf,train->args_len);
            send(netfd, &train->type, sizeof(int), MSG_NOSIGNAL);
            send(netfd, &train->args_len, sizeof(int), MSG_NOSIGNAL);
            send(netfd,train->args_val,train->args_len,MSG_NOSIGNAL);
            break;
    default:
        
        break;
    }
    return 0;
}


int recv_resolver(int target,int args_len,char*args,char*now_path_buf,int sockfd)
{
    
    // printf("client res type:%d\n", target);
    switch (target)
    {
    case CD_SUCCESS:
        client_cd(target,args_len,args,sockfd,now_path_buf);
        break;
    case  LS_SUCCESS:
        client_ls(target,args_len,args,sockfd,now_path_buf);
        break;
    case RMDIR_SUCCESS:
        client_rmdir(target,args_len,args,sockfd,now_path_buf);
        break;
    case MKDIR_SUCCESS:
        client_mkdir(target,args_len,args,sockfd,now_path_buf);
        break;
    case REMOVE_SUCCESS:
        client_rmfile(target,args_len,args,sockfd,now_path_buf);    
        break;
    case DIR_ERR: 
        printf("%s\n", args);    
        break;
    case RES_GETS_COMFIRM:
        client_gets_comfirm(target, args_len, args, sockfd, now_path_buf);
        break;
    case RES_PUTS_COMFIRM:
        client_puts_comfirm(target, args_len, args, sockfd, now_path_buf);
        break;
    default:
        printf("接收错误\n");
        break;
    }
    return 0;
}

int split_path(const char *input, char **out_parent, char **out_name) {
    if (!input || !out_parent || !out_name) return -1;

    // 去掉末尾多余的 '/'
    size_t len = strlen(input);
    while (len > 1 && input[len - 1] == '/') {
        len--;
    }

    char *tmp = (char *)malloc(len + 1);
    if (!tmp) return -1;
    memcpy(tmp, input, len);
    tmp[len] = '\0';

    // 找最后一个 '/'
    char *slash = strrchr(tmp, '/');
    if (!slash) {
        // 没有 '/'，父路径为 "."
        *out_parent = strdup(".");
        *out_name   = strdup(tmp);
    } else if (slash == tmp) {
        *out_parent = strdup("/");
        *out_name   = strdup(slash + 1);
    } else {
        *slash = '\0';
        *out_parent = strdup(tmp);
        *out_name   = strdup(slash + 1);
    }

    free(tmp);
    if (!*out_parent || !*out_name) {
        free(*out_parent);
        free(*out_name);
        return -1;
    }
    return 0;
}

